package com.luo.d3s.ec.infrastructure.database;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.luo.d3s.core.application.dto.PageQuery;
import com.luo.d3s.core.application.dto.PageResponse;
import com.luo.d3s.core.util.Optionals;
import com.luo.d3s.ec.domain.category.model.Category;
import com.luo.d3s.ec.domain.category.model.CategoryName;
import com.luo.d3s.ec.domain.category.repository.CategoryRepository;
import com.luo.d3s.ec.infrastructure.database.convertor.CategoryConvertor;
import com.luo.d3s.ec.infrastructure.database.convertor.PageConvertor;
import com.luo.d3s.ec.infrastructure.database.dao.CategoryMapper;
import com.luo.d3s.ec.infrastructure.database.dataobject.CategoryDo;
import com.luo.d3s.share.model.BizId;
import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Category仓库实现类
 *
 * @author luohq
 * @date 2023-01-05 14:26
 */
@Repository
public class CategoryRepositoryImpl implements CategoryRepository {

    private CategoryMapper categoryMapper;

    public CategoryRepositoryImpl(CategoryMapper categoryMapper) {
        this.categoryMapper = categoryMapper;
    }

    @Override
    public Category save(Category category) {
        //转换分类数据对象
        CategoryDo categoryDo = CategoryConvertor.toCategoryDo(category);
        //ID已存在，则修改
        Boolean existCategory = this.existCategoryId(category.getId());
        if (existCategory) {
            this.categoryMapper.updateById(categoryDo);
            return category;
        }
        //ID不存在，则新增
        this.categoryMapper.insert(categoryDo);
        //返回分类实体信息
        return CategoryConvertor.toCategory(categoryDo);
    }

    @Override
    public Category findById(BizId bizId) {
        //查询分类信息
        CategoryDo categoryDo = this.categoryMapper.selectById(bizId.getValue());
        if (null == categoryDo) {
            return null;
        }
        //转换分类实体
        return CategoryConvertor.toCategory(categoryDo);
    }

    @Override
    public void removeById(BizId bizId) {
        //根据ID删除分类信息
        this.categoryMapper.deleteById(bizId.getValue());
    }

    @Override
    public Boolean existCategoryName(CategoryName categoryName, BizId excludeCategoryId) {
        Long excludeCategoryDoId = Optionals.defaultNull(excludeCategoryId, BizId::getValue);
        //验证分类名称是否存在
        Boolean exists = this.categoryMapper.exists(Wrappers.<CategoryDo>lambdaQuery()
                .eq(CategoryDo::getCategoryName, categoryName.getValue())
                .ne(Objects.nonNull(excludeCategoryDoId), CategoryDo::getId, excludeCategoryDoId)
        );
        return exists;
    }

    @Override
    public Boolean existCategoryId(BizId categoryId) {
        //验证分类ID是否存在
        Boolean exists = this.categoryMapper.exists(Wrappers.<CategoryDo>lambdaQuery()
                .eq(CategoryDo::getId, categoryId.getValue())
        );
        return exists;
    }

    @Override
    public List<Category> findByParentId(BizId parentCategoryId) {
        //根据上级分类ID查询子分类列表
        List<CategoryDo> categoryDoList = this.categoryMapper.selectList(Wrappers.<CategoryDo>lambdaQuery()
                .eq(CategoryDo::getParentCategoryId, parentCategoryId.getValue()));
        if (CollectionUtils.isEmpty(categoryDoList)) {
            return null;
        }
        //转换分类实体
        return categoryDoList.stream()
                .map(CategoryConvertor::toCategory)
                .collect(Collectors.toList());
    }

    @Override
    public void deleteByIds(List<BizId> categoryIds) {
        if (CollectionUtils.isEmpty(categoryIds)) {
            return;
        }
        //批量删除分类
        List<Long> batchIds = categoryIds.stream()
                .map(BizId::getValue)
                .collect(Collectors.toList());
        this.categoryMapper.deleteBatchIds(batchIds);
    }

    @Override
    public PageResponse<Category> findPage(PageQuery pageQuery, LocalDateTime createTimeStart, LocalDateTime createTimeEnd) {
        Page<CategoryDo> pageResult = this.categoryMapper.selectPage(
                PageConvertor.toPage(pageQuery),
                Wrappers.<CategoryDo>lambdaQuery()
                        .ge(ObjectUtils.isNotNull(createTimeStart), CategoryDo::getCreateTime, createTimeStart)
                        .le(ObjectUtils.isNotNull(createTimeEnd), CategoryDo::getCreateTime, createTimeEnd));
        return PageConvertor.toPageResponse(pageResult, CategoryConvertor::toCategory);
    }
}
